package com.atjava.nebula.core.dao.ibatis;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;

import com.atjava.nebula.core.dao.BaseDao;
import com.atjava.nebula.core.dao.GenericDao;
import com.atjava.nebula.core.dao.ibatis.projection.IProjection;
import com.atjava.nebula.core.exception.baseExp.DataAccessException;
import com.atjava.nebula.core.model.BaseModel;
import com.atjava.nebula.core.page.Page;
import com.atjava.nebula.core.util.generic.GenericsUtils;

/**泛型Dao的IBatis实现
 * </p>
 * 子类只要在类定义时指定所管理Entity的Class, 即拥有对单个Entity对象的CRUD操作. 
 * 
 * @author kyo
 *
 * @param <T> 所要操作的实体类
 * @param <ID> 实体类的主键
 */
public  class GenericIBatisDao<T extends BaseModel ,ID extends Serializable> extends SqlMapClientDaoSupport implements GenericDao<T,ID> {

	/**
	 * DAO所管理的Entity类型.
	 */
	public Class<T> entityClass;
	private BaseDao baseDao;

	/**做为基类时，自动调用的构造方法
	 * 在构造函数中将泛型T.class赋给entityClass.
	 */
	@SuppressWarnings("unchecked")
	protected GenericIBatisDao() {
		entityClass = (Class<T>) GenericsUtils.getSuperClassGenricType(getClass());
	}
	
	/**直接生成该类时需要调用该构造方法
	 * <p>
	 * （Java里无法直接取到当前类实例的泛型类型，只有在被继承时子类能取到父类的泛型类型
	 * 所以这里保留了一个带有Class参数的构造方法）
	 * @param entityClass 该DAO所要操作的实体类 (可传入如：Addv.class)
	 */
	public GenericIBatisDao(Class<T> entityClass){
		this.entityClass=entityClass;	
	}

	
	/**
	 * 取得entityClass.
	 * <p/>
	 * JDK1.4不支持泛型的子类可以抛开Class<T> entityClass,重载此函数达到相同效果。
	 */
	protected Class<T> getEntityClass() {
		return entityClass;
	}
	
	public BaseDao getBaseDao() {
		return baseDao;
	}

	public void setBaseDao(BaseDao baseDao) {
		//SqlMapClientDaoSupport daoSup=baseDao.getClass().getSuperclass();
		BaseIBatisDao bIBDao=(BaseIBatisDao) baseDao;
		this.setDataSource(bIBDao.getDataSource());		
		this.setSqlMapClientTemplate(bIBDao.getSqlMapClientTemplate());
		this.baseDao = baseDao;
	}
	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#getById(java.io.Serializable)
	 */
	public T getById(ID id) throws DataAccessException {
		return getBaseDao().getById(entityClass,id);

	}	
	

	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#getAll()
	 */
	public List<T> getAll() throws DataAccessException{
		return getBaseDao().getAll(entityClass);
	}
	
	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#create(com.atjava.nebula.core.model.BaseModel)
	 */
	public ID create(T o) throws DataAccessException{
		return getBaseDao().create(o);
	}
	

	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#updateById(com.atjava.nebula.core.model.BaseModel)
	 */
	public void updateById(T o)  throws DataAccessException{
		getBaseDao().updateById(o);
	}

	/* 
	 * @see com.atjava.nebula.core.dao.GenericDao#updateAllById(com.atjava.nebula.core.model.BaseModel)
	 */
	public void updateAllById(T obj) throws DataAccessException {
		getBaseDao().updateAllById(obj);
	}
	
	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#remove(com.atjava.nebula.core.model.BaseModel)
	 */
	public void remove(T o) throws DataAccessException{
		getBaseDao().remove(o);
	}
	

	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#removeById(java.io.Serializable)
	 */
	public void removeById(ID id) throws DataAccessException{
		getBaseDao().removeById(entityClass,id);
	}
	
	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#ExecSql(java.lang.String)
	 */
	public List<Map<String,Object>> ExecSql(String sql) throws DataAccessException {
		return getBaseDao().ExecSql(sql);
	}
	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#ExecSql(java.lang.String, java.lang.Object[])
	 */
	public List<Map<String, Object>> ExecSql(String sql, Object... params)
			throws DataAccessException {
		return getBaseDao().ExecSql(sql, params);
	}

	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#list(com.atjava.nebula.core.model.BaseModel)
	 */
	public List<T> list(T obj) throws DataAccessException {
		return getBaseDao().list(obj);
	}


	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#list(com.atjava.nebula.core.dao.ibatis.Condition)
	 */
	public List<T> list(Condition cond)
			throws DataAccessException {
		return getBaseDao().list(entityClass, cond);
	}
	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#list(com.atjava.nebula.core.dao.ibatis.projection1.IProjection, com.atjava.nebula.core.dao.ibatis.Condition)
	 */
	public List<Map<String, Object>> list(IProjection projection, Condition cond) throws DataAccessException {
		return getBaseDao().list(entityClass, projection, cond);
	}

	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#list(com.atjava.nebula.core.model.BaseModel, com.atjava.nebula.core.dao.ibatis.projection1.IProjection)
	 */
	public List<Map<String, Object>> list(T obj, IProjection projection) throws DataAccessException {
		return getBaseDao().list(obj, projection);
	}
	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#page(com.atjava.nebula.core.model.BaseModel, int, int)
	 */
	public Page<T> page(T obj, int pageNo, int pageSize) throws DataAccessException {
		return getBaseDao().page(obj, pageNo, pageSize);
	}



	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#page(com.atjava.nebula.core.dao.ibatis.Condition, int, int)
	 */
	public Page<T> page( Condition cond, int pageNo,
			int pageSize) throws DataAccessException {
		return getBaseDao().page(entityClass, cond, pageNo, pageSize);
	}

	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#page(com.atjava.nebula.core.dao.ibatis.projection1.IProjection, com.atjava.nebula.core.dao.ibatis.Condition, int, int)
	 */
	public Page<Map<String, Object>> page(IProjection projection, Condition cond, int pageNo, int pageSize) throws DataAccessException {
		return getBaseDao().page(entityClass, projection, cond, pageNo, pageSize);
	}

	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#page(com.atjava.nebula.core.model.BaseModel, com.atjava.nebula.core.dao.ibatis.projection1.IProjection, int, int)
	 */
	public Page<Map<String, Object>> page(T obj, IProjection projection, int pageNo, int pageSize) throws DataAccessException {
		return getBaseDao().page(obj, projection, pageNo, pageSize);
	}

	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#count(com.atjava.nebula.core.dao.ibatis.Condition)
	 */
	public Integer count(Condition cond) throws DataAccessException {
		return  getBaseDao().count(entityClass, cond);
	}

	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#count(com.atjava.nebula.core.model.BaseModel)
	 */
	public Integer count(T obj) throws DataAccessException {
		return  getBaseDao().count(obj);
	}

	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#count()
	 */
	public Integer count() throws DataAccessException {
		return getBaseDao().count(entityClass);
	}
	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#count(com.atjava.nebula.core.dao.ibatis.projection.IProjection, com.atjava.nebula.core.dao.ibatis.Condition)
	 */
	public Integer count(IProjection projection, Condition cond) throws DataAccessException {
		return getBaseDao().count(entityClass,projection,cond);
	}
	/* 
	 * @see com.atjava.nebula.core.dao.GenricDao#count(com.atjava.nebula.core.model.BaseModel, com.atjava.nebula.core.dao.ibatis.projection.IProjection)
	 */
	public Integer count(T obj, IProjection projection) throws DataAccessException {
		return getBaseDao().count(obj,projection);
	}

}
